package cn.com.twoke.app.pin_dou_dou.utils;

import java.awt.Color;

/**
 * 颜色空间转换工具类，专门用于RGB到Lab的转换
 */
public class ColorLabUtils {
    
    // D65标准光源
    private static final double[] D65 = {95.047, 100.000, 108.883};
    
    /**
     * 将RGB颜色转换为XYZ颜色空间
     * @param color RGB颜色
     * @return XYZ颜色值数组 [x, y, z]
     */
    public static double[] rgbToXyz(Color color) {
        return rgbToXyz(color.getRed(), color.getGreen(), color.getBlue());
    }
    
    /**
     * 将RGB颜色分量转换为XYZ颜色空间
     * @param r 红色分量 (0-255)
     * @param g 绿色分量 (0-255)
     * @param b 蓝色分量 (0-255)
     * @return XYZ颜色值数组 [x, y, z]
     */
    public static double[] rgbToXyz(int r, int g, int b) {
        // 归一化到0-1范围
        double rn = r / 255.0;
        double gn = g / 255.0;
        double bn = b / 255.0;
        
        // Gamma校正
        rn = (rn > 0.04045) ? Math.pow((rn + 0.055) / 1.055, 2.4) : rn / 12.92;
        gn = (gn > 0.04045) ? Math.pow((gn + 0.055) / 1.055, 2.4) : gn / 12.92;
        bn = (bn > 0.04045) ? Math.pow((bn + 0.055) / 1.055, 2.4) : bn / 12.92;
        
        // 转换到XYZ
        rn *= 100;
        gn *= 100;
        bn *= 100;
        
        double x = rn * 0.4124 + gn * 0.3576 + bn * 0.1805;
        double y = rn * 0.2126 + gn * 0.7152 + bn * 0.0722;
        double z = rn * 0.0193 + gn * 0.1192 + bn * 0.9505;
        
        return new double[]{x, y, z};
    }
    
    /**
     * 将XYZ颜色值转换为Lab颜色空间
     * @param x X分量
     * @param y Y分量
     * @param z Z分量
     * @return Lab颜色值数组 [l, a, b]
     */
    public static double[] xyzToLab(double x, double y, double z) {
        // 相对于D65标准化
        double xn = x / D65[0];
        double yn = y / D65[1];
        double zn = z / D65[2];
        
        // 非线性变换
        xn = (xn > 0.008856) ? Math.pow(xn, 1.0/3) : (7.787 * xn) + (16.0/116);
        yn = (yn > 0.008856) ? Math.pow(yn, 1.0/3) : (7.787 * yn) + (16.0/116);
        zn = (zn > 0.008856) ? Math.pow(zn, 1.0/3) : (7.787 * zn) + (16.0/116);
        
        double l = (116 * yn) - 16;
        double a = 500 * (xn - yn);
        double b = 200 * (yn - zn);
        
        return new double[]{l, a, b};
    }
    
    /**
     * 直接将RGB颜色转换为Lab颜色空间
     * @param color RGB颜色
     * @return Lab颜色值数组 [l, a, b]
     */
    public static double[] rgbToLab(Color color) {
        double[] xyz = rgbToXyz(color);
        return xyzToLab(xyz[0], xyz[1], xyz[2]);
    }
    
    /**
     * 直接将RGB颜色分量转换为Lab颜色空间
     * @param r 红色分量 (0-255)
     * @param g 绿色分量 (0-255)
     * @param b 蓝色分量 (0-255)
     * @return Lab颜色值数组 [l, a, b]
     */
    public static double[] rgbToLab(int r, int g, int b) {
        double[] xyz = rgbToXyz(r, g, b);
        return xyzToLab(xyz[0], xyz[1], xyz[2]);
    }
}